import { Injectable } from '@angular/core';
import { Circle as CircleStyle, Fill, Icon, Stroke, Style, Text } from 'ol/style';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource, Cluster } from 'ol/source';
import { createEmpty, extend, getHeight, getWidth } from 'ol/extent';
import AnimatedCluster from 'ol-ext/layer/AnimatedCluster';
import { MapDataService, EQUIPMENT_CODE, MARKER_TYPE, INCIDENT_CODE, MarkerToPng_Event } from './map-data.service';
import { ToolsService, MessagesService } from 'app/shared/service';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import { Subject } from 'rxjs';
import { MapViewService } from './map-view.service';

export const StatusToIcon = {
    OK: 'Active',
    Faulty: 'Failed',
    OFFLINE: 'Offline',
    FAULTY: 'Failed'
};

@Injectable()
export class MapClusteredService {
    private _textFill = new Fill({
        color: '#fff'
    });

    private _textStroke = new Stroke({
        color: 'rgba(0,0,0,0.6)',
        width: 3
    });

    // 当前分辨率
    private _currentResolutionMap = {
        [MARKER_TYPE.EQ_LEGEND_MARKER]: null,
        [MARKER_TYPE.IR_LEGEND_MARKER]: null
    };

    // 当前范围内最大Feature
    private _maxFeatureCountMap = {
        [MARKER_TYPE.EQ_LEGEND_MARKER]: null,
        [MARKER_TYPE.IR_LEGEND_MARKER]: null
    };

    // 所有设备类型
    constructor(
        private mapDataService: MapDataService,
        private tools: ToolsService,
        private msg: MessagesService,
        private mapViewService: MapViewService
    ) {}

    // Operation alarm图标聚合图层
    /*     returnOperationAlarm() {
            const layer = new VectorLayer({
                source: new VectorSource(),
                visible: false,
                zIndex: 21,
                style: (features: any, resolution: number) => this.operationAlarmClustered(features, resolution)
            });
            return layer;
        } */

    // Operation alert图标聚合图层
    /*     returnOperationAlert() {
            const layer = new VectorLayer({
                source: new VectorSource(),
                visible: false,
                zIndex: 21,
                style: (features: any, resolution: number) => this.operationAlertClustered(features, resolution)
            });
            return layer;
        } */

    // 返回Equipment 或 Incident 聚合图层
    returnClusterLayer(type: 'equipment' | 'incident', typeCode?: EQUIPMENT_CODE[]) {
        const AnimatedClusterLayer = new AnimatedCluster({
            name: 'Cluster',
            source: new Cluster({
                distance: 30,
                source: new VectorSource()
            }),
            visible: false,
            zIndex: 21,
            animationDuration: 700,
            style: (features: any, resolution: number) => this._layerFeaturesClustered(features, resolution)
        });

        if (type === 'equipment') {
            this.getEquipmentVectorSource().subscribe(source => AnimatedClusterLayer.setSource(source));
        } else {
            this.getIncidentVectorSource().subscribe(source => AnimatedClusterLayer.setSource(source));
        }

        return AnimatedClusterLayer;
    }

    // 拿到Incident图层的源
    getIncidentVectorSource(typeCodes: INCIDENT_CODE[] = []) {
        const _ss = new Subject<any>();
        this.mapDataService.getIRFeatureData(typeCodes).subscribe(
            res => {
                if (res['messagecode'] === '000000') {
                    const features = [];
                    this.tools
                        .calc(res, 'data', [])
                        // .slice(0, 20) // 截取前20条
                        .forEach(feature => {
                            const incidentType = feature['type'];
                            const iconSrc = `content/images/icons/incident/${MarkerToPng_Event[incidentType]}.png`;
                            const featureParam = {
                                geometry: new Point([feature['start_X_Coor'], feature['start_Y_Coor']]),
                                name: MARKER_TYPE.IR_LEGEND_MARKER,
                                prototype: {
                                    iconSrc,
                                    data: {
                                        type: MARKER_TYPE.IR_LEGEND_MARKER,
                                        render: feature
                                    }
                                }
                            };
                            const temporary = new Feature(featureParam);
                            features.push(temporary);
                        });
                    _ss.next(
                        new Cluster({
                            distance: 30,
                            source: new VectorSource({
                                features
                            })
                        })
                    );
                } else {
                    this.msg.error(res['message']);
                }
            },
            err => this.msg.error(err)
        );
        return _ss.asObservable();
    }

    // 拿到设备图层的源
    getEquipmentVectorSource(typeCodes: EQUIPMENT_CODE[] = [], typePlusStatus: string[] = []) {
        const _ss = new Subject<any>();
        this.mapDataService.getEquipmentFeatureData(typeCodes).subscribe(
            res => {
                if (res['code'] === '000000') {
                    const features = [];

                    this.tools
                        .calc(res, 'data', [])
                        // .slice(0, 1) // 截取前1条
                        .filter(feature => {
                            const equipmentType = feature['eqtType'];
                            // feature['status'] = StatusToIcon[feature['status']];
                            const equipmentStatus = StatusToIcon[feature['status']];
                            if (typePlusStatus.length > 0) {
                                return typePlusStatus.includes(`${equipmentType}_${equipmentStatus}`);
                            } else {
                                return true;
                            }
                        })
                        .forEach(feature => {
                            const equipmentType = feature['eqtType'];
                            const equipmentStatus = StatusToIcon[feature['status']];
                            const iconSrc = `content/images/icons/equipment/${equipmentType}_${equipmentStatus}.png`;
                            const featureParam = {
                                geometry: new Point([feature.longitude, feature.latitude]),
                                name: MARKER_TYPE.EQ_LEGEND_MARKER,
                                prototype: {
                                    iconSrc,
                                    data: {
                                        type: MARKER_TYPE.EQ_LEGEND_MARKER,
                                        render: feature
                                    }
                                }
                            };
                            const temporary = new Feature(featureParam);
                            features.push(temporary);
                        });
                    _ss.next(
                        new Cluster({
                            distance: 30,
                            source: new VectorSource({
                                features
                            })
                        })
                    );
                } else {
                    this.msg.error(res['msg']);
                }
            },
            err => this.msg.error(err)
        );
        return _ss.asObservable();
    }

    // 图层聚合样式设置
    private _layerFeaturesClustered(features: any, resolution: number) {
        const originalFeature = features.get('features')[0];
        const type = this.tools.calc(originalFeature, 'values_.prototype.data.type', null);
        if (resolution !== this._currentResolutionMap[type]) {
            this._calculateClusterInfo(features, resolution);
            this._currentResolutionMap[type] = resolution;
        }

        let style;
        const size = features.get('features').length;
        if (size > 1) {
            style = new Style({
                image: new CircleStyle({
                    radius: 20,
                    fill: new Fill({
                        color: [255, 153, 0, Math.min(0.8, 0.4 + size / this._maxFeatureCountMap[type])]
                    })
                }),
                text: new Text({
                    text: size.toString(),
                    fill: this._textFill,
                    stroke: this._textStroke,
                    offsetY: 1,
                    textAlign: 'center',
                    font: '16px "Arial", sans-serif'
                })
            });
        } else {
            // 设置单个图标显示图案
            if (type === MARKER_TYPE.EQ_LEGEND_MARKER) {
                style = this._createEquipmentsStyle(originalFeature);
            }
            if (type === MARKER_TYPE.IR_LEGEND_MARKER) {
                style = this._createIncidentSytle(originalFeature);
            }
        }

        return style;
    }

    // 设置单个incident图标样式
    private _createIncidentSytle(feature: any) {
        const props = this.tools.calc(feature, 'values_.prototype.data.render', null);
        if (props) {
            const incidentType = props['type'];
            const iconSrc = `content/images/icons/incident/${MarkerToPng_Event[incidentType]}.png`;
            const radius = 5 + 20 * (6 - 5);
            return new Style({
                image: new Icon({
                    anchor: [0.5, 0.5],
                    anchorXUnits: 'fraction',
                    anchorYUnits: 'fraction',
                    src: iconSrc,
                    scale: 0.8
                }),
                text: new Text({
                    text: props['ir_ID'].slice(-4),
                    font: '12px "Arial", sans-serif',
                    textBaseline: 'middle',
                    offsetY: 20,
                    fill: new Fill({
                        color: '#555'
                    }),
                    stroke: new Stroke({
                        color: '#fff'
                    })
                })
            });
        }
    }

    // 设置未聚合的单个设备图标样式
    private _createEquipmentsStyle(feature: any) {
        // const props = feature.getProperties();
        const props = this.tools.calc(feature, 'values_.prototype.data.render', null);
        // const iconSource = `content/images/icons/${properties.eqt_type}_${properties.status_code}.png`;
        if (props) {
            const equipmentType = props['eqtType'];
            const equipmentStatus = StatusToIcon[props['status']];
            const iconSrc = `content/images/icons/equipment/${equipmentType}_${equipmentStatus}.png`;
            const radius = 5 + 20 * (6 - 5);
            return new Style({
                image: new Icon({
                    anchor: [0.5, 0.5],
                    anchorXUnits: 'fraction',
                    anchorYUnits: 'fraction',
                    src: iconSrc,
                    scale: 0.8
                }),
                text: new Text({
                    text: props['eqtId'],
                    font: '12px "Arial", sans-serif',
                    textBaseline: 'middle',
                    offsetY: 20,
                    fill: new Fill({
                        color: '#555'
                    }),
                    stroke: new Stroke({
                        color: '#fff'
                    })
                })
            });
        }
    }

    // 计算范围内feature特征数量
    private _calculateClusterInfo(features: any, resolution: number) {
        const originalFeature = features.get('features')[0];
        const type = this.tools.calc(originalFeature, 'values_.prototype.data.type', null);

        this._maxFeatureCountMap[type] = 0;
        let feature, radius;
        for (let i = features.length - 1; i >= 0; --i) {
            feature = features[i];
            const originalFeatures = feature.get('features');
            const extent = createEmpty();
            let j = void 0,
                jj = void 0;
            for (j = 0, jj = originalFeatures.length; j < jj; ++j) {
                extend(extent, originalFeatures[j].getGeometry().getExtent());
            }
            this._maxFeatureCountMap[type] = Math.max(this._maxFeatureCountMap[type], jj);
            radius = 0.25 * (getWidth(extent) + getHeight(extent)) / resolution;
            feature.set('radius', radius);
        }
    }
}
